﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using Sub.Function;
using System.Xml;
using System.Collections;
using System.Data.Linq.Mapping;
using System.Linq.Expressions;
using System.Data.Linq;
using System.Web;

namespace Sub.Function
{
    [DataContract]
    public class PageFilter
    {
        #region fields
        string _UserName = "";
        string _ViewPath = "";
        string _FieldSearch = "";
        string _ValueSearch = "";
        bool _IsLoadAll = false;
        int _pIndex;
        int _pSize;
        int _total;
        string _FilterExpression = "";
        string _SortExpression = "";
        TokenResult _TokenKey;
        List<string> lsOrds;
        Guid _UserId;
        EnumType.eActionErrorType _ActionError = EnumType.eActionErrorType.None;
        #endregion

        public PageFilter()
        {
            //nothing
        }
        [DataMember]
        public int PageIndex
        {
            get
            {
                return _pIndex;
            }
            set
            {
                _pIndex = value;
            }
        }
        [DataMember]
        public int PageSize
        {
            get
            {
                return _pSize;
            }
            set
            {
                _pSize = value;
            }
        }
        [DataMember]
        public bool IsLoadAll
        {
            get
            {
                return _IsLoadAll;
            }
            set
            {
                _IsLoadAll = value;
            }
        }
        [DataMember]
        public int Total
        {
            get
            {
                return _total;
            }
            set
            {
                _total = value;
            }
        }
        [DataMember]
        public string SortExpression
        {
            get
            {
                return _SortExpression;
            }
            set
            {
                _SortExpression = value;
            }
        }
        [DataMember]
        public string FieldSearch
        {
            get
            {
                return _FieldSearch;
            }
            set
            {
                _FieldSearch = value;
            }
        }
        [DataMember]
        public string ValueSearch
        {
            get
            {
                return _ValueSearch;
            }
            set
            {
                _ValueSearch = value;
            }
        }
        [DataMember]
        public string ViewPath
        {
            get
            {
                return _ViewPath;
            }
            set
            {
                _ViewPath = value;
            }
        }
        [DataMember]
        public string UserName
        {
            get
            {
                return _UserName;
            }
            set
            {
                _UserName = value;
            }
        }
        [DataMember()]
        public Guid UserID
        {
            get
            {
                string XML = Associate.Decrypt(this.TokenKey.Data);
                XmlDocument doc = new XmlDocument();
                doc.LoadXml("<root>" + XML + "</root>");
                var strRet = doc.DocumentElement.SelectSingleNode("//User").InnerText;
                return new Guid(strRet);
            }
            set
            {
            }
        }
        Hashtable _parameters;
        [DataMember]
        public Hashtable parameters
        {
            get
            {
                if (_parameters == null)
                {
                    _parameters = new Hashtable();
                }
                return _parameters;
            }

        }
        public object this[string key]
        {
            get
            {
                if (parameters.ContainsKey(key))
                {
                    return parameters[key];
                }
                else
                {
                    return null;
                }
            }
            set
            {
                if (parameters.ContainsKey(key))
                {
                    parameters[key] = value;
                }
                else
                {
                    parameters.Add(key, value);
                }
            }
        }


        public int GetInt(string key)
        {
            var val = this[key];
            if (val == null)
            {
                return 0;
            }
            else
            {
                return Convert.ToInt32(val.ToString());
            }
        }




        private void FixByTagName(XmlDocument doc, string NodeName)
        {
            var node = doc.DocumentElement.SelectSingleNode("//" + NodeName);
            if (node == null)
            {
                return;
            }

            var nodes = node.SelectNodes("//Member[@MemberType='Field']");
            string xml = "";
            foreach (XmlNode n in nodes)
            {
                if (node.InnerXml.IndexOf(n.OuterXml) > -1)
                {
                    var field = n.Attributes["FieldName"].Value;

                    xml += @" <ConstantExpression NodeType=""Constant"">
                  <Value>" + parameters[field] + @"</Value>
                  <Type>
                    <Type Name=""" + parameters[field].GetType().ToString() + @""" />
                  </Type>
                </ConstantExpression>";
                }
            }
            node.InnerXml = xml;
        }
        [DataMember]
        public TokenResult TokenKey
        {
            get
            {
                _TokenKey.PageFilter = this;
                return _TokenKey;
            }
            set
            {
                _TokenKey = value;

            }
        }
        [DataMember]
        public EnumType.eActionErrorType ActionError
        {
            get
            {
                return _ActionError;
            }
            set
            {
                _ActionError = value;
            }
        }     
        
        public Dictionary<string, bool> GetSortList()
        {
            var ret = new Dictionary<string, bool>();
            if (string.IsNullOrEmpty(_SortExpression))
            {
                return ret;
            }
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(_SortExpression);


            var node = doc.DocumentElement.ChildNodes[0];
            if (node.Attributes["desc"] != null)
            {
                ret.Add(node.InnerText, false);

            }
            else
            {
                ret.Add(node.InnerText, true);
            }
            return ret;
        }

        public void AddOrderField(string field)
        {
            if (_SortExpression == "")
            {
                _SortExpression = "<root><node>" + field + "</node></root>";
            }
            else
            {
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(_SortExpression);
                var node = doc.CreateNode(XmlNodeType.Element, "node", null);
                node.InnerText = field;
                //Add them node con vao node goc
                doc.ChildNodes[0].AppendChild(node);
                _SortExpression = doc.OuterXml;

            }
        }
        public void AddOrderDescField(string field)
        {
            if (_SortExpression == "")
            {
                _SortExpression = @"<root><node desc=""1"">" + field + "</node></root>";
            }
            else
            {
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(_SortExpression);
                var node = doc.CreateNode(XmlNodeType.Element, "node", null);
                var attr = doc.CreateAttribute("desc", null);
                attr.Value = "1";
                node.Attributes.Append(attr);
                node.InnerText = field;
                _SortExpression = doc.OuterXml;

            }
        }

        public bool IsSearchAll
        {

            get
            {
                if (string.IsNullOrEmpty(this.FieldSearch) ||
                    string.IsNullOrEmpty(this.ValueSearch))
                    return false;
                return this.FieldSearch.ToLower() == "all";
            }
        }
        public bool IsSearchByField
        {

            get
            {
                if (string.IsNullOrEmpty(this.FieldSearch) ||
                    string.IsNullOrEmpty(this.ValueSearch))
                    return false;
                return this.FieldSearch.ToLower() != "all";
            }
        }
          
        public int TotalPages
        {
            get
            {
                return this.Total / this.PageSize + ((this.Total % this.PageSize) > 0 ? 1 : 0);
            }
        }

        public string SQL = "";
        public void SetFilter<T>(Expression<Func<T, bool>> where)
        {
            DataContext db = new DataContext("");
            var list = new List<T>();
            IQueryable<T> qr = list.AsQueryable();



            qr = qr.Where(where);


            var cmd = db.GetCommand(qr);
            SQL = cmd.CommandText;


        }
        [DataMember]
        public string FilterExpression { get; set; }
        [System.Diagnostics.DebuggerStepperBoundary]
        [System.Diagnostics.DebuggerStepThrough]
        public PageFilter Add(string FieldName, string Operator, object value)
        {
            string ValidateOperator = "[=][!=][>=][<=]>[<][<>][Contains][>]";
            if (ValidateOperator.IndexOf("[" + Operator + "]") == -1)
            {
                throw (new Exception("'" + Operator + "' is invalidation"));
            }
            string xml = "";
            if (FilterExpression != "")
            {
                xml = Associate.Decrypt(FilterExpression);

            }
            if (value != null)
            {
                xml = xml + @"<and field=""" + FieldName + @""" operator=""" + HttpContext.Current.Server.HtmlEncode(Operator) + @""" value=""" + value.ToString() + @""" type=""" + value.GetType().FullName + @"""/>";
            }
            else
            {
                xml = xml + @"<and field=""" + FieldName + @""" operator=""" + HttpContext.Current.Server.HtmlEncode(Operator) + @"""  />";
            }
            FilterExpression = Associate.Encrypt(xml);
            return this;
        }

        public PageFilter AddOr(string FieldName, string Operator, object value)
        {
            string xml = "";
            if (FilterExpression != "")
            {
                xml = Associate.Decrypt(FilterExpression);

            }
            xml = xml + @"<or field=""" + FieldName + @""" operator=""" + Operator + @""" value=""" + value.ToString() + @""" type=""" + value.GetType().FullName + @"""/>";
            FilterExpression = Associate.Encrypt(xml);
            return this;
        }
        
        [DataMember]
        public string ErrorContent { get; set; }
    }
}
